<?php
class Ajax
{
	public $base_url;
	public $directFormats = array('json', 'xml', 'html');

	/**
   * How do we valide callbacks so no funny stuff is tried
   * 0 - No validation: Not suggested for use, could leave things open
   * 1 - Validate against an array of possible class base names
   * 2 - Only allow registered callback methods and classes PREFERRED!
   * @access private
   * @publicarray
   */ 
	public $validateCallbacks = 2;

	/**
   * What are the valid base class and method names?
   * @access private
   * @publicarray
   */
	public $callbackFilter = array('Pjq');

	/**
   * Array of all registered methods
   * @access private
   * @publicarray
   */
	public $registered_methods = array();

	/**
   * Array of all registered objects
   * @access private
   * @publicarray
   */
	public $registered_objects = array();
	public function __construct()
	{
		$front_controller=Registry::getInstance();
		$front_controller=$front_controller->get("frontcontroller");
		$this->base_url=$front_controller->getBaseUrl();
	}
	
	function getBaseUrl()
	{
		return $this->base_url;
	}
	public function link_remote($module="",$controller="",$action="",$update="",$complete="",$content="")
	{

	}
	public function startAjax()
	{
		echo '<script type="text/javascript" src="',$this->getBaseUrl(),'javascript/jquery.js"></script>';
		echo '<script type="text/javascript" src="',$this->getBaseUrl(),'javascript/pjq.js"></script>';
	}


	function processIncoming() {
		if($this->validateCallbacks AND !$this->validateCallback($_REQUEST['callback'])) {
			return false;
		}
	
		// Here we check the handler to see if we have a direct Format request, in this case we return that
		// formatted data directly
		if(isset($_REQUEST['handler']) AND in_array($_REQUEST['handler'], $this->directFormats)) {
			$data = $this->getData($_REQUEST['callback'],$this->getParams(), $_REQUEST['handler']);
		} else {
			require_once('ajax/Ajax_Response.php');
			$responseObject = Ajax_Response::getInstance();
			$controller=$this->registered_objects[$_REQUEST["callback"]];
			$responseObject->processCallback(array($_REQUEST['callback'],$controller), $this->getParams());
			$data = $responseObject->getResponse();
		}
		
		if($data) {
			echo $data;
		}
	}


	/**
   * Handle incoming data, verify callback and either getData or build the response
   * 
   * @param string
   * @return booleon
   */
	function validateCallback($callback) {
		$valid = 0;
	   
		switch($this->validateCallbacks) {
			case 1:
				/**
         * Only allow callbacks that match our "filter" base strings
         */
				$obj = is_array($callback);
				
				foreach($this->callbackFilter as $value) {
					if(($obj AND (strpos($callback[0], $value) !== false)) OR (!$obj AND (strpos($callback, $value) !== false))) {
						$valid = 1;
						break;
					}
				}
				break;
			case 2:
				/**
         * We want to be strict, only allow registered callbacks
         */
				
				$obj = is_array($callback);
				if($obj) 
				{
					if(isset($this->registered_objects[$callback[0]]) AND ((in_array($callback[1], $this->registered_objects[$callback[0]])) OR ($this->registered_objects[$callback[0]] === 1)) )
					 {
						$valid = 1;
						break;
					}
				} 
				else 
				{
					if(in_array($callback, $this->registered_methods)||array_key_exists($callback,$this->registered_objects)) {
						$valid = 1;
						
						break;
					}
				}
				break;
			default:
				/**
         * Any callback is valid
         */
				$valid = 1;
				break;
		}
		return $valid;
	}

	/**
   * Register our callback methods or specific method within an object
   * 
   * @param mixed
   */
	function registerCallback($callback) {
		if(is_array($callback)) {
			
			$this->registered_objects[$callback[0]] = $callback[1];
		} else {
			$this->registered_methods[] = $callback;
		}
	}

	/**
   * Register an object and all its methods
   * 
   * @param object
   */
	function registerObject($object) {
		$this->registered_objects[$object] = 1;
	}

	/**
   * Register a string as a base callback filter
   * 
   * @param string
   */
	function registerFilter($filter) {
		$this->callbackFilter[] = $filter;
	}

	/**
   * getData is for direct requests, no further handling of the response is done
   * 
   * @param mixed
   * @param array
   * @param string
   * @return mixed
   */
	function getData($callback, $params, $format = '') {
		$obj=$this->registered_objects[$callback];
		$data=$obj->$callback($params);
		switch($format) {
			case 'json':
				$edata = json_encode($data);
				break;
			default:
				/**
         * Right now xml and html formats have to be handled by the user function
         * In the future there should be an xml encoder to allow easy changing between
         * json and xml
         */
				$edata = $data;
				break;
		}
		return $edata;
	}

	/**
   * We should prob do some sort of filtering here
   */
	function getParams() {
		$params = null;
		if(isset($_REQUEST['params'])) {
			$params = $_REQUEST['params'];
		}
		return $params;
	}

}